Nested Functions

Contents|Index|Previous|Next
Nested functions

A nested function is a function defined inside another function. (Nested functions are not supported for GNU C++.) The nested function’s name is local to the block where it is defined. For instance, the following example shows how to define a nested function named square, and then calls it twice.

    foo (double a, double b)
    {
       double square (double z) { return z * z; }

       return square (a) + square (b);
    }

The nested function can access all the variables of the containing function that are visible at the point of its definition. This is called lexical scoping. For instance, the following example shows a nested function which uses an inherited variable named offset.

    bar (int *array, int offset, int size)
    {
      int access (int *array, int index)
         { return array[index + offset]; }
      int i;
      ...
      for (i = 0; i < size; i++)
         ... access (array, i) ...
    }

Nested function definitions are permitted within functions in the places where variable definitions are allowed; that is, in any block, before the first statement in the block.

It is possible to call the nested function from outside the scope of its name by storing its address or passing the address to another function, as in the following.

    hack (int *array, int size)
    {
      void store (int index, int value)
        { array[index] = value; }

      intermediate (store, size);
    }

Within this block, the function intermediate receives the address of store as an argument. If intermediate calls store, the arguments given to store are used to store into array. But this technique works only so long as the containing function (hack, in the previous example) does not exit.

If you try to call the nested function through its address after the containing function has exited, all hell will break loose. If you try to call it after a containing scope level has exited, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it’s not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe.

GNU CC implements taking the address of a nested function using a technique called trampolines.
A paper describing trampolines is available as `http://master.debian.org/~karlheg/Usenix88-lexic.pdf`.

A nested function can jump to a label inherited from a containing function, provided the label was explicitly declared in the containing function (see Locally Declared Labels). Such a jump returns instantly to the containing function, exiting the nested function which did the goto and any intermediate functions as well. The following is an example.

    bar (int *array, int offset, int size)
    {
       __label__ failure;
       int access (int *array, int index)
           {
          if (index > size)
             goto failure;
          return array[index + offset];
          }
       int i;
       ...
       for (i = 0; i < size; i++)
         ...access (array, i) ...
    ...
    return 0;

    /* Control comes here from access if it detects an error. */
    failure:
    return -1;
    }

A nested function always has internal linkage. Declaring one with extern is erroneous. If you need to declare the nested function before its definition, use auto (which is otherwise meaningless for function declarations).

    bar (int *array, int offset, int size)
    {
          __label__ failure;
          auto int access (int *, int);
          ...
          int access (int *array, int index)
          {
            if (index > size)
              goto failure;
            return array[index + offset];
          }
          ...
    }

Top|Contents|Index|Previous|Next